<template>
  <VxeModal
    ref="modalRef"
    v-bind="getBindValue"
    v-model="openRef"
    :before-hide-method="beforeHideFn"
    @show="showEvent"
    @hide="hideEvent"
    @confirm="confirmEvent"
    @cancel="cancelEvent"
    @close="closeEvent"
    @zoom="zoomEvent"
    @resize="resizeEvent"
    @move="moveEvent"
  >
    <template #title v-if="!$slots.title">
      <ModalHeader :help-message="getProps.helpMessage" :title="getMergeProps.title" @dblclick="titleDbClickEvent" />
    </template>

    <template #footer v-if="!$slots.footer">
      <ModalFooter v-bind="getMergeProps" @ok="okEvent" @cancel="cancelEvent">
        <template #[item]="data" v-for="item in Object.keys($slots)">
          <slot :name="item" v-bind="data || {}"></slot>
        </template>
      </ModalFooter>
    </template>

    <template #default>
      <div @keydown="keydownEvent" @keyup="keyupEvent" tabindex="0" style="height: 100%">
        <slot></slot>
      </div>
    </template>

    <!-- <template #[item]="data" v-for="item in Object.keys(omit($slots, 'default'))">
      <slot :name="item" v-bind="data || {}"></slot>
    </template> -->
  </VxeModal>
</template>
<script lang="ts" setup>
  import type { ModalEventTypes, VxeModalDefines, VxeModalInstance } from 'vxe-pc-ui';

  import type { ModalMethods, ModalProps } from './typing';

  import { computed, getCurrentInstance, ref, unref, useAttrs, watch, watchEffect } from 'vue';

  import { isFunction, isNumber, /* omit, */ pick } from '@eacloud/utils';

  // import { buildShortUUID } from '@/utils/uuid';
  import { deepMerge } from '@/utils';
  import { VxeModal } from 'vxe-pc-ui';

  import ModalFooter from './components/ModalFooter.vue';
  import ModalHeader from './components/ModalHeader.vue';
  import { modalProps } from './props';
  import { ModalPropNames, VxeModalPropNames } from './typing';

  defineOptions({ name: 'AdVxeModal' });

  const props = defineProps(modalProps);
  const emit = defineEmits([
    'register',
    'openChange',
    'update:open',
    'show',
    'hide',
    'confirm',
    'cancel',
    'close',
    'zoom',
    'resize',
    'move',
    'ok',
    'keydown',
    'keyup',
  ]);
  const attrs = useAttrs();
  const modalRef = ref<VxeModalInstance>();
  const openRef = ref(false);
  const propsRef = ref<null | Partial<ModalProps>>(null);

  const getMergeProps = computed((): ModalProps => {
    const mergeProps = {
      ...props,
      ...unref(propsRef),
    };
    return mergeProps;
  });

  const getProps = computed((): ModalProps => {
    const opt = {
      ...unref(getMergeProps),
      // open: unref(openRef),
      cancelButtonProps: undefined,
      okButtonProps: undefined,
      title: undefined,
    };
    return {
      ...opt,
    };
  });

  const getBindValue = computed((): ModalProps => {
    const attr = {
      ...attrs,
      ...unref(getMergeProps),
      // open: unref(openRef),
    };
    return pick(attr, VxeModalPropNames);
  });

  const getMinWidth = computed(() => {
    const value = unref(getProps)?.minWidth;
    if (isNumber(value)) {
      return `${value}px`;
    } else {
      return value;
    }
  });
  const getMinHeight = computed(() => {
    const value = unref(getProps)?.minHeight;
    if (isNumber(value)) {
      return `${value}px`;
    } else {
      return value;
    }
  });
  const getMaxWidth = computed(() => {
    const value = unref(getProps)?.maxWidth;
    if (isNumber(value)) {
      return `${value}px`;
    } else {
      return value;
    }
  });
  const getMaxHeight = computed(() => {
    const value = unref(getProps)?.maxHeight;
    if (isNumber(value)) {
      return `${value}px`;
    } else {
      return value;
    }
  });

  /** 弹窗对象 */
  const getModal = computed(() => unref(modalRef));

  const modalMethods: ModalMethods = {
    getModal: () => unref(getModal),
    isOpen: () => unref(openRef),
    setModalProps,
  };

  /**
   * @description: 设置modal参数
   */
  function setModalProps(props: Partial<ModalProps>): void {
    // Keep the last setModalProps
    const propsTmp = pick(props, [...VxeModalPropNames, ...ModalPropNames]);
    propsRef.value = deepMerge(unref(propsRef) || ({} as any), propsTmp);
    if (Reflect.has(props, 'open')) {
      openRef.value = !!props.open;
    }
  }

  const instance = getCurrentInstance();
  if (instance) {
    emit('register', modalMethods, instance.uid);
  }

  watchEffect(() => {
    openRef.value = !!props.open;
  });

  watch(
    () => unref(openRef),
    (v) => {
      emit('openChange', v);
      emit('update:open', v);
      if (v) {
        const boxElement = getModal.value?.getBox();
        if (boxElement) {
          if (getMinWidth.value) {
            boxElement.style.minWidth = getMinWidth.value;
          } else {
            boxElement.style.removeProperty('min-width');
          }
          if (getMinHeight.value) {
            boxElement.style.minHeight = getMinHeight.value;
          } else {
            boxElement.style.removeProperty('min-height');
          }
          if (getMaxWidth.value) {
            boxElement.style.maxWidth = getMaxWidth.value;
          } else {
            boxElement.style.removeProperty('max-width');
          }
          if (getMaxHeight.value) {
            boxElement.style.maxHeight = getMaxHeight.value;
          } else {
            boxElement.style.removeProperty('max-height');
          }
        }
      }
    },
    {
      immediate: false,
    },
  );

  /** 弹窗标题双击事件 */
  async function titleDbClickEvent() {
    // if (props.showZoom) {
    //   await getModal.value?.zoom();
    // }
  }

  /** 在窗口隐藏之前执行，可以返回 Error 阻止关闭，支持异步。点击关闭，或者按 ESC 键之前可以拦截。 */
  async function beforeHideFn(params: { type: ModalEventTypes }) {
    if (props.closeFunc && isFunction(props.closeFunc)) {
      const isClose: boolean = await props.closeFunc(params);
      // openRef.value = !isClose;
      // return;
      if (!isClose) {
        return new Error();
      }
    }
  }

  /** 在窗口显示时会触发该事件 */
  async function showEvent(e: VxeModalDefines.ShowEventParams) {
    emit('show', e);
  }
  /** 在窗口隐藏时会触发该事件 */
  async function hideEvent(e: VxeModalDefines.HideEventParams) {
    emit('hide', e);
  }
  /** 点击确定按钮时会触发该事件 */
  async function confirmEvent(e: VxeModalDefines.ConfirmEventParams) {
    emit('confirm', e);
  }
  /** 取消事件 */
  async function cancelEvent(e: Recordable) {
    openRef.value = false;
    emit('cancel', e);
  }
  /** 点击关闭按钮时会触发该事件 */
  async function closeEvent(e: VxeModalDefines.CloseEventParams) {
    emit('close', e);
  }
  /** 窗口缩放时会触发该事件 */
  async function zoomEvent(e: VxeModalDefines.ZoomEventParams) {
    const boxElement = getModal.value?.getBox();
    if (boxElement) {
      if (e?.type.toLowerCase() === 'minimize') {
        boxElement.style.removeProperty('min-width');
      } else {
        if (getMinWidth.value) {
          boxElement.style.minWidth = getMinWidth.value;
        }
      }
    }
    emit('zoom', e);
  }
  /** 窗口调整大小时会触发该事件 */
  async function resizeEvent(e: VxeModalDefines.ResizeEventParams) {
    emit('resize', e);
  }
  /** 窗口移动时会触发该事件 */
  async function moveEvent(e: VxeModalDefines.MoveEventParams) {
    emit('move', e);
  }
  /** 确认事件 */
  function okEvent(e: Recordable) {
    // openRef.value = false;
    emit('ok', e);
  }
  /** 键盘按下时会触发该事件 */
  async function keydownEvent(e: KeyboardEvent) {
    emit('keydown', e);
  }
  /** 键盘弹起时会触发该事件 */
  async function keyupEvent(e: KeyboardEvent) {
    emit('keyup', e);
  }
</script>

<style lang="scss">
  // .vxe-modal--wrapper .vxe-modal--content {
  //   padding: 0;
  // }

  //解决ant组件被遮挡问题
  .ant-select-dropdown {
    z-index: 999999999;
  }

  .ant-cascader-dropdown {
    z-index: 999999999;
  }

  .ant-select-tree-list {
    z-index: 999999999;
  }

  .ant-picker-dropdown {
    z-index: 999999999;
  }

  .ant-dropdown {
    z-index: 999999999;
  }

  .ant-message {
    z-index: 999999999;
  }

  .ant-tooltip {
    z-index: 999999999;
  }
</style>
